const pkrDir = require("pkg-dir").sync;
const npmInstall = require("npminstall");
const pathExists = require("path-exists").sync;
const fs = require("fs-extra");
const path = require("path");
const { isObject } = require("@cheng-cli-dev/utils");
const formatPath = require("@cheng-cli-dev/format-path");
const {
  getNpmLatestVersion,
  getDefaultRegistry,
} = require("@cheng-cli-dev/get-npm-info");

class Package {
  constructor(options) {
    if (!options) {
      throw new Error("实例化Package 构造函数options不能为空");
    }
    if (!isObject(options)) {
      throw new Error("实例化Package 构造函数options必须是一个对象");
    }
    this.targetPath = options.targetPath;
    // //远程package的存储路径
    this.storePath = options.storePath;
    this.packageName = options.packageName;
    this.packageVersion = options.packageVersion;
    //package缓存目录前缀
    this.cacheFilePathPrefix = this.packageName.replace("/", "_");
  }
  //获取当前package的路径
  get cacheFilePath() {
    return path.resolve(
      this.storePath,
      `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`
    );
  }
  //拼接路径
  getLatestCacheFilePath(packageName) {
    return path.resolve(
      this.storePath,
      `_${this.cacheFilePathPrefix}@${this.packageVersion}@${packageName}`
    );
  }
  async prepare() {
    if (this.storePath && !pathExists(this.storePath)) {
      fs.mkdirpSync(this.storePath);
    }
    if (this.packageVersion === "latest") {
      this.packageVersion = await getNpmLatestVersion(this.packageName);
    }
  }
  async exists() {
    //1.判断缓存目录存在情况
    if (this.storePath) {
      await this.prepare();
      return pathExists(this.storePath, this.cacheFilePath);
    } else {
      //2.判断用户传入的绝对路径是否存在
      return pathExists(this.targetPath);
    }
  }
  //安装package
  async install() {
    await this.prepare();
    return await npmInstall({
      root: this.targetPath,
      storeDir: this.storePath,
      registry: getDefaultRegistry(),
      pkgs: [
        {
          name: this.packageName,
          version: this.packageVersion,
        },
      ],
    });
  }
  //更新package 获取package的最新版本如果不一致并且本地路径也不存在进行npm install 更新即可
  async update() {
    await this.prepare();
    const latestVersion = await getNpmLatestVersion(this.packageName);
    const latestFilePath = this.getLatestCacheFilePath(this.packageName);
    if (!pathExists(latestFilePath)) {
      await npmInstall({
        root: this.targetPath,
        storeDir: this.storePath,
        registry: getDefaultRegistry(),
        pkgs: [
          {
            name: this.packageName,
            version: latestVersion,
          },
        ],
      });
    }
    this.packageVersion = latestVersion;
  }
  //获取入口文件路径
  getRootFilePath() {
    //获取init模块的package.json路径 因为用户传入的路径不一定在当前package.json路径
    const _getRootFilePath = (targetPath) => {
      let rootPagPath = pkrDir(targetPath);
      try {
        //获取当前路径的package.json
        const pkg = require(path.resolve(rootPagPath, "package.json"));
        //通过package.json获取入口文件
        if (pkg && pkg.main) {
          return formatPath(path.resolve(rootPagPath, pkg.main));
        }
        return null;
      } catch (e) {
        throw new Error(e);
      }
    };
    if (this.storePath) {
      return _getRootFilePath(this.cacheFilePath);
    } else {
      return _getRootFilePath(this.targetPath);
    }
  }
}
module.exports = Package;
